home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / chaserog.zip / SRC_ROG.ZIP / COMBAT.QC < prev    next >
Text File  |  1997-05-09  |  9KB  |  392 lines

  1. // combat.qc
  2.  
  3. float IsExplosionDamage;
  4.  
  5. void() T_MissileTouch;
  6. void() info_player_start;
  7. void(entity targ, entity attacker) ClientObituary;
  8.  
  9. void() monster_death_use;
  10.  
  11. //============================================================================
  12.  
  13. /*
  14. ============
  15. CanDamage
  16.  
  17. Returns true if the inflictor can directly damage the target.  Used for
  18. explosions and melee attacks.
  19. ============
  20. */
  21. float(entity targ, entity inflictor) CanDamage =
  22. {
  23. // bmodels need special checking because their origin is 0,0,0
  24.     if (targ.movetype == MOVETYPE_PUSH)
  25.     {
  26.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  27.         if (trace_fraction == 1)
  28.             return TRUE;
  29.         if (trace_ent == targ)
  30.             return TRUE;
  31.         return FALSE;
  32.     }
  33.     
  34.     traceline(inflictor.origin, targ.origin, TRUE, self);
  35.     if (trace_fraction == 1)
  36.         return TRUE;
  37.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  38.     if (trace_fraction == 1)
  39.         return TRUE;
  40.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  41.     if (trace_fraction == 1)
  42.         return TRUE;
  43.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  44.     if (trace_fraction == 1)
  45.         return TRUE;
  46.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  47.     if (trace_fraction == 1)
  48.         return TRUE;
  49.  
  50.     return FALSE;
  51. };
  52.  
  53.  
  54. /*
  55. ============
  56. Killed
  57. ============
  58. */
  59. void() cam_startdeathview; // Rob
  60.  
  61. void(entity targ, entity attacker) Killed =
  62. {
  63.     local entity oself;
  64.  
  65.     oself = self;
  66.     self = targ;
  67.     
  68.     //if (self.health < -99)
  69.     //    self.health = -99;        // don't let sbar look bad if a player
  70.  
  71.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  72.     {    // doors, triggers, etc
  73.         self.th_die ();
  74.         self = oself;
  75.         return;
  76.     }
  77.  
  78.     self.enemy = attacker;
  79.  
  80. // bump the monster counter
  81.     if (self.flags & FL_MONSTER)
  82.     {
  83.         killed_monsters = killed_monsters + 1;
  84.         WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  85.     }
  86.  
  87. // PGM - guarantee gib if killed by buzzsaw.
  88.     if (attacker.classname == "buzzsaw" || 
  89.         attacker.classname == "Vengeance" ||
  90.         attacker.classname == "pendulum")
  91.         self.health = -99;
  92.  
  93. // PGM - gravity fix!
  94.     self.gravity = 1.0;
  95.     ClientObituary(self, attacker);
  96.     
  97.     self.takedamage = DAMAGE_NO;
  98.     self.touch = SUB_Null;
  99.  
  100.     monster_death_use();
  101.     self.th_die ();
  102.  
  103.     // Rob; prevent internal C from tilting the view after
  104.     // QC has already initiated all death processes
  105.     if ((self.flags & FL_CLIENT))
  106.     {
  107.         if ((self.dest2_x & CHSCAM_ON))
  108.             self.health = 1;
  109.         else if (! self.waterlevel)
  110.         {
  111.             self.health = 1;
  112.             cam_startdeathview();
  113.         }
  114.     }
  115.  
  116.     self = oself;
  117. };
  118.  
  119. // ====
  120. // Function prototype for shield impact handler.
  121. // ====
  122. float(entity targ, entity inflictor, entity attacker, float damage) shield_hit;
  123.  
  124. /*
  125. ============
  126. T_Damage
  127.  
  128. The damage is coming from inflictor, but get mad at attacker
  129. This should be the only function that ever reduces health.
  130. ============
  131. */
  132. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  133. {
  134.     local    vector    dir;
  135.     local    entity    oldself;
  136.     local    float    save;
  137.     local    float    take;
  138.     
  139.     if (!targ.takedamage)
  140.         return;
  141.  
  142.     if (targ.classname == "trigger_explosion")
  143.     {
  144.         if ( IsExplosionDamage != 1)
  145.             return;
  146.     }
  147.     IsExplosionDamage = 0;
  148.  
  149.     if (targ.items2 & IT2_SHIELD)
  150.     {
  151.         // Allow some damage to pass through.
  152.         damage = shield_hit(targ, inflictor, attacker, damage);
  153.         if (damage == 0)
  154.             return;
  155.     }
  156.  
  157. // used by buttons and triggers to set activator for target firing
  158.     damage_attacker = attacker;
  159.  
  160. // check for quad damage powerup on the attacker
  161.     if (attacker.super_damage_finished > time)
  162.         damage = damage * 4;
  163. // rune power up (Black Magic)
  164.     if (deathmatch)
  165.         damage = RuneApplyBlack(damage, attacker);
  166.  
  167. // save damage based on the target's armor level
  168.  
  169. //ZOID--
  170.     if (TeamArmorDam(targ, inflictor, attacker, damage))
  171.         save = ceil(targ.armortype*damage);
  172.     else
  173.         save = 0;
  174. //--ZOID
  175.  
  176.     if (save >= targ.armorvalue)
  177.     {
  178.         save = targ.armorvalue;
  179.         targ.armortype = 0;    // lost all armor
  180.         targ.items2 = targ.items2 - 
  181.                         (targ.items2 & (IT2_ARMOR1 | IT2_ARMOR2 | IT2_ARMOR3));
  182.     }
  183.     
  184.     targ.armorvalue = targ.armorvalue - save;
  185.     take = ceil(damage-save);
  186.  
  187. // add to the damage total for clients, which will be sent as a single
  188. // message at the end of the frame
  189. // FIXME: remove after combining shotgun blasts?
  190.     if (targ.flags & FL_CLIENT)
  191.     {
  192.         targ.dmg_take = targ.dmg_take + take;
  193.         targ.dmg_save = targ.dmg_save + save;
  194.         targ.dmg_inflictor = inflictor;
  195.     }
  196.  
  197. // figure momentum add
  198.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  199.     {
  200.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  201.         dir = normalize(dir);
  202.         targ.velocity = targ.velocity + dir*damage*8;
  203.     }
  204.     
  205. // check for godmode or invincibility
  206.     if (targ.flags & FL_GODMODE)
  207.         return;
  208.     if (targ.invincible_finished >= time)
  209.     {
  210.         if (targ.invincible_sound < time)
  211.         {
  212.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  213.             targ.invincible_sound = time + 2;
  214.         }
  215.         return;
  216.     }
  217.  
  218. // team play damage avoidance
  219. //    if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  220. //        return;
  221. //ZOID--
  222.     if (!TeamHealthDam(targ, inflictor, attacker, damage))
  223.         return; // same team
  224. //--ZOID
  225.  
  226. // rune power up (Earth Magic)
  227.     if (deathmatch)
  228.         take = RuneApplyEarth(take, targ);
  229.         
  230. // do the damage
  231.     targ.health = targ.health - take;
  232.             
  233.     if (targ.health <= 0)
  234.     {
  235.         Killed (targ, attacker);
  236.         return;
  237.     }
  238.  
  239. // react to the damage
  240.     oldself = self;
  241.     self = targ;
  242.  
  243.     if ( (self.flags & FL_MONSTER) && attacker != world)
  244.     {
  245.     // get mad unless of the same class (except for soldiers)
  246.         if (self != attacker && attacker != self.enemy)
  247.         {
  248.             if ( (self.classname != attacker.classname) 
  249.             || (self.classname == "monster_army" ) )
  250.             {
  251.                 if ( self.classname != "monster_dragon")
  252.                 {
  253.                     if (self.enemy.classname == "player")
  254.                         self.oldenemy = self.enemy;
  255.                     self.enemy = attacker;
  256.                     FoundTarget ();
  257.                 }
  258.             }
  259.         }
  260.     }
  261.         
  262.     if (self.th_pain)
  263.     {
  264.         self.th_pain (attacker, take);
  265.     // nightmare mode monsters don't go into pain frames often
  266.         if (skill == 3)
  267.             self.pain_finished = time + 5;        
  268.     }
  269.  
  270.     self = oldself;
  271. };
  272.  
  273. /*
  274. ============
  275. T_EELZap
  276. ============
  277. */
  278. void(entity inflictor, entity attacker, float damage) T_EELZap =
  279. {
  280.     local    float     points;
  281.     local    entity    head;
  282.     local    vector    org;
  283.  
  284.     head = findradius(inflictor.origin, damage+40);
  285.     
  286.     while (head)
  287.     {
  288.         if (head.takedamage)
  289.         {
  290.             org = head.origin + (head.mins + head.maxs)*0.5;
  291.             points = 0.5*vlen (inflictor.origin - org);
  292.             if (points < 0)
  293.                 points = 0;
  294.             points = damage - points;
  295.             if (head == attacker)
  296.                 points = points * 0.5;
  297.             if (points > 0)
  298.             {
  299.                 if (CanDamage (head, inflictor))
  300.                 {    // eels take no damage from this attack
  301.                     if (head.classname != "monster_eel" && 
  302.                         (head.flags & FL_INWATER))                    
  303.                         T_Damage (head, inflictor, attacker, points);
  304.                 }
  305.             }
  306.         }
  307.         head = head.chain;
  308.     }
  309. };
  310.  
  311. /*
  312. ============
  313. T_RadiusDamage
  314. ============
  315. */
  316. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  317. {
  318.     local    float     points;
  319.     local    entity    head;
  320.     local    vector    org;
  321.  
  322.     IsExplosionDamage = 1;
  323.  
  324.     head = findradius(inflictor.origin, damage+40);
  325.     
  326.     while (head)
  327.     {
  328.         if (head != ignore)
  329.         {
  330.             if (head.takedamage)
  331.             {
  332.                 org = head.origin + (head.mins + head.maxs)*0.5;
  333.                 points = 0.5*vlen (inflictor.origin - org);
  334.                 if (points < 0)
  335.                     points = 0;
  336.                 points = damage - points;
  337.                 if (head == attacker)
  338.                     points = points * 0.5;
  339.                 if (points > 0)
  340.                 {
  341.                     if (CanDamage (head, inflictor))
  342.                     {    // shambler takes half damage from all explosions
  343.                         if (head.classname == "monster_shambler")                        
  344.                             T_Damage (head, inflictor, attacker, points*0.5);
  345.                         else
  346.                             T_Damage (head, inflictor, attacker, points);
  347.                     }
  348.                 }
  349.             }
  350.         }
  351.         head = head.chain;
  352.     }
  353. };
  354.  
  355. /*
  356. ============
  357. T_BeamDamage
  358. ============
  359. */
  360. void(entity attacker, float damage) T_BeamDamage =
  361. {
  362.     local    float     points;
  363.     local    entity    head;
  364.     
  365.     head = findradius(attacker.origin, damage+40);
  366.     
  367.     while (head)
  368.     {
  369.         if (head.takedamage)
  370.         {
  371.             points = 0.5*vlen (attacker.origin - head.origin);
  372.             if (points < 0)
  373.                 points = 0;
  374.             points = damage - points;
  375.             if (head == attacker)
  376.                 points = points * 0.5;
  377.             if (points > 0)
  378.             {
  379.                 if (CanDamage (head, attacker))
  380.                 {
  381.                     if (head.classname == "monster_shambler")                        
  382.                         T_Damage (head, attacker, attacker, points*0.5);
  383.                     else
  384.                         T_Damage (head, attacker, attacker, points);
  385.                 }
  386.             }
  387.         }
  388.         head = head.chain;
  389.     }
  390. };
  391.  
  392.